import numpy as np
import pandas as pd
import streamlit as st
from PIL import Image
from matplotlib import pyplot as plt

#  创建页面的主要标题，渲染成 H1 标签
st.title("My first app")
# 创建一个相对较小的标题，渲染成 H2 标签
st.header("This is a header")
# 创建相对较小的标题，比st.header()还要小
st.subheader("This is a subheader")

st.write("Hello, *World!* :sunglasses:")

# 纯文本内容
st.subheader('--------------纯文本内容----------------------------')
st.text('''
静夜思
床前明月光，疑是地上霜。
举头望明月，低头思故乡。
''')

# Markdown
st.subheader('--------------Markdown----------------------------')
st.markdown('''
# 静夜思
床前**明月**光，疑是地上霜。
举头望**明月**，低头思故乡。
''')

# 代码段
st.subheader('--------------代码段----------------------------')
st.code('''
def bubble_sort(arr):
    n = len(arr)
    # 遍历所有数组元素
    for i in range(n):
        # 最后 i 个元素已经排好序，不需要再比较
        for j in range(0, n-i-1):
            # 如果元素比下一个元素大，则交换它们
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
''', language='python')

# 通用显示方法
#   它是一个多功能的函数，可以接受多种类型的参数，包括Markdown格式的字符串、数字、DataFrame、图表等。
st.subheader('--------------通用显示方法----------------------------')
# 字符串
st.write("这是一段文本。")

# 数字
st.write(42)

# 列表
st.write([1, 2, 3])

# 字典
st.write({"key": "value"})

st.write(True)

# 数据框（DataFrame）
df = pd.DataFrame({"Column 1": [1, 2, 3], "Column 2": ["A", "B", "C"]})
st.write(df)

# 多参数用法
st.write("这是一个字符串", 42, [1, 2, 3], {"key": "value"})

# 自定义渲染
fig, ax = plt.subplots()
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y)
st.write(fig)

# 表格数据
# st.dataframe()：以表格的形式呈现数据，支持Pandas的特有功能，如排序、过滤等，并且会自动适应数据框的大小，如果数据框太大，它会自动启用滚动条。
# 参数如下：
#   ①width：UI元素的期望宽度，单位为像素，类型为Int或None，如果是None的话，Streamlit将基于页面宽度计算元素宽度。
#   ②height：UI元素的期望高度，单位为像素，类型为Int或None。
#
# st.table()：用于显示通用表格数据，不仅支持Pandas，还可以处理列表、元组等可迭代数据结构。但st.table仅用于显示数据，而不提供诸如排序和过滤等数据框专有功能。

st.subheader('--------------表格数据----------------------------')
# 随机数，生成5行10列的随机数
random_data = np.random.rand(5, 10)
df = pd.DataFrame(random_data, columns=[f'列-{i}' for i in range(1, 11)])

# st.dataframe还可以传入一个Pandas Styler对象来修改所渲染的DataFrame的样式
# st.dataframe(df)
st.dataframe(df.style.highlight_max(axis=0), width=500, height=300)
st.table(df)

# 显示JSON
# st.json()：主要用于展示JSON格式的数据，会自动适应JSON数据的大小，如果数据较大会自动启用滚动条，并且可以处理包含嵌套结构的复杂JSON数据，以树状结构的形式展示。
st.subheader('--------------JSON----------------------------')
st.json({
    'foo': 'bar',
    'baz': 'boz',
    'stuff': [
        'stuff 1',
        'stuff 2',
        'stuff 3',
        'stuff 5',
    ],
})

# 显示pyplot图表
# st.pyplot()：用于显示指定的matplotlib.pyplot图表。
#
# Matplotlib支持几种不同的后端。如果在Streamlit中使用Matplotlib出现问题， 可以尝试将后端设置为 “TkAgg”:
st.subheader('--------------pyplot图表----------------------------')
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label='sin(x)')
plt.plot(x, y2, label='cos(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
st.pyplot()

# 显示地图
# st.map()：显示地图及叠加的数据点，支持自动居中与自动缩放。
# 参数：
#   data：要显示的数据，必须包含字段lat、lon、latitude或longitude，可以是DataFrame、Styler、数组以及其他可迭代对象等类型：
#   zoom：缩放等级。
#   use_container_width (bool): 是否使用容器的整个宽度。如果设置为True，地图将占据整个容器的宽度。
st.subheader('--------------地图----------------------------')

# 显示图像
# st.image()：是Streamlit中用于在应用程序中显示图像的函数。它可以接受多种输入格式，包括文件路径、URL、图像的字节数据等。
# 参数如下：
#   默认参数为st.image(image, caption=None, width=None, use_column_width=False, clamp=False, channels='RGB', format='JPEG')
#   image：要显示的图像，类型可以是numpy.ndarray,[numpy.ndarray],BytesIO,str,或[str])。单色图像为(w,h)或(w,h,1)，彩色图像为(w,h,3)，RGBA图像为(w,h,4)，也可以指定一个图像url，或url列表
#   caption：图像标题，字符串。如果显示多幅图像，caption应当是字符串列表。
#   width：图像宽度，None表示使用图像自身宽度。
#   use_column_width：如果设置为True，则使用列宽作为图像宽度。
#   clamp：是否将图像的像素值压缩到有效域（0~255），仅对字节数组图像有效。
#   channels：图像通道类型，'RGB'或'BGR'，默认值：RGB。
#   format：图像格式：'JPEG'或'PNG')，默认值：JPEG。
st.subheader('--------------图像----------------------------')

image = Image.open('test.jpg')

st.image(image, caption='标题', width=500)

# 显示视频
# st.video()：是Streamlit中用于在应用程序中显示视频的函数。它支持多种视频来源，包括本地文件、URL和字节数据。
# 参数：
#   format(str or None):视频格式，可以是"mp4"、"webm"等。如果设置为None，Streamlit将尝试根据文件扩展名自动识别视频格式。
#   start_time(int):视频开始播放的时间（以秒为单位）。
st.subheader('--------------视频----------------------------')
video_file = open('test.mp4', 'rb')
video_bytes = video_file.read()

# 本地视频
st.video(video_bytes, format="mp4", start_time=2)
# 网络视频
st.video("http://www.w3school.com.cn/i/movie.mp4")
